package com.sneaker.shower.service.impl;

import com.sneaker.shower.common.BizException;
import com.sneaker.shower.service.FileService;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service
public class FileServiceImpl implements FileService {
    ExecutorService executorService = Executors.newFixedThreadPool(4);
    @Value("${domain}")
    private String domain;
    private String baseDir = "/file";

    /**
     * 根据指定大小和指定精度压缩图片
     *  @param inputStream 源图片地址
     * @param des         目标图片地址
     * @param desFileSize 指定图片大小，单位kb
     */
    private static void commpressPicForScale(InputStream inputStream, File des,
                                             long desFileSize, String fileType) {
        try {

            // 1、先转换成jpg
            Thumbnails.of(inputStream).outputQuality(1f).scale(1f).outputFormat(fileType).toFile(des);
            // 递归压缩，直到目标文件大小小于desFileSize
            commpressPicCycle(des, desFileSize, 0.8, fileType);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void commpressPicCycle(File srcFileJPG, long desFileSize,
                                          double accuracy, String fileType) throws IOException {
        long srcFileSizeJPG = srcFileJPG.length();
        // 2、判断大小，如果小于500kb，不压缩；如果大于等于500kb，压缩
        if (srcFileSizeJPG <= desFileSize * 1024) {
            return;
        }
        // 计算宽高
        BufferedImage bim = ImageIO.read(srcFileJPG);
        int srcWdith = bim.getWidth();
        int srcHeigth = bim.getHeight();
        double accuracy1 = desFileSize * 1024d * accuracy / srcFileSizeJPG;
        double accuracy2 = Math.sqrt(accuracy1);

        int desWidth = new BigDecimal(accuracy2 * srcWdith).intValue();
        int desHeight = new BigDecimal(accuracy2 * srcHeigth).intValue();

        Thumbnails.of(srcFileJPG)
                .size(desWidth, desHeight)
                .outputQuality(accuracy2).outputFormat(fileType).toFile(srcFileJPG);
        commpressPicCycle(srcFileJPG, desFileSize, accuracy, fileType);
    }

    @PostConstruct
    public void init() {
        File file = new File(baseDir);
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    @Override
    public String upload(File file) {
        String fileName = file.getName();
        try {
            return upload(fileName, new FileInputStream(file));
        } catch (FileNotFoundException e) {
            throw new BizException("文件上传失败");
        }
    }

    @Override
    public String upload(MultipartFile multipartFile) {
        String fileName = multipartFile.getOriginalFilename();
        try {
            return upload(fileName, multipartFile.getInputStream());
        } catch (IOException e) {
            throw new BizException("文件上传失败");
        }
    }

    @Override
    public String upload(String fileName, InputStream is) {
        String fileType = fileName != null && fileName.contains(".") ? fileName.substring(fileName.lastIndexOf(".") + 1) : null;
        String neo = UUID.randomUUID().toString().replaceAll("-", "");
        String result = neo + "." + fileType;
        try {
            File file = new File(baseDir + File.separator + result);
            file.createNewFile();
            int available = is.available();
            commpressPicForScale(is, file, Math.max((available / 5120), 2048), fileType);
        } catch (IOException e) {
            throw new BizException("文件上传失败");
        }
        return domain + result;
    }

    @Override
    public String download(String fileName, OutputStream os) {
        try {
            File file = new File(baseDir + File.separator + fileName);
            InputStream is = new FileInputStream(file);
            IOUtils.copy(is, os);
            os.flush();
            os.close();
            is.close();
            return file.getName();
        } catch (IOException e) {
            throw new BizException("文件下载失败");
        }
    }

    @Override
    public File download(String fileName) {
        String[] split = fileName.split("=");
        return new File(baseDir + File.separator + split[1]);
    }

}
